home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World's Largest Collection of Windows Software
/
The World's Largest Collection of Windows Software - Disc 2.iso
/
textproc
/
_j1
/
tex2rtf
/
src
/
tex2any.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-26
|
54KB
|
1,991 lines
/*
* File: tex2any.cc
* Purpose: Conversion utility for LaTeX files
*
* wxWindows 1.50
* Copyright (c) 1993 Artificial Intelligence Applications Institute,
* The University of Edinburgh
*
* Author: Julian Smart
* Date: 7-9-93
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice, author statement and this permission
* notice appear in all copies of this software and related documentation.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
* IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
* UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
* DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
* THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <wx.h>
#include <ctype.h>
#include "tex2any.h"
#include <stdlib.h>
#include <time.h>
/*
* Variables accessible from clients
*
*/
TexChunk * DocumentTitle = NULL;
TexChunk * DocumentAuthor = NULL;
TexChunk * DocumentDate = NULL;
char * CurrentLabel = NULL;
int DocumentStyle = LATEX_REPORT;
int MinorDocumentStyle = 0;
wxPathList TexPathList;
char * BibliographyStyleString = copystring("plain");
char * DocumentStyleString = copystring("report");
int ParSkip = 0;
int ParIndent = 0;
int normalFont = 10;
int smallFont = 8;
int tinyFont = 6;
int largeFont1 = 12;
int LargeFont2 = 14;
int LARGEFont3 = 18;
int hugeFont1 = 20;
int HugeFont2 = 24;
int HUGEFont3 = 28;
// Section font sizes
int chapterFont = LARGEFont3;
int sectionFont = LargeFont2;
int subsectionFont = largeFont1;
/*
* Section numbering
*
*/
int chapterNo = 0;
int sectionNo = 0;
int subsectionNo = 0;
int subsubsectionNo = 0;
int figureNo = 0;
/*
* Other variables
*
*/
FILE *CurrentOutput1 = NULL;
FILE *CurrentOutput2 = NULL;
FILE *Inputs[15];
int CurrentInputIndex = 0;
char TexFileRoot[300];
char TexBibName[300]; // Bibliography output file name
char TexTmpBibName[300]; // Temporary bibliography output file name
static int currentColumn = 0;
char currentArgData[2000];
Bool haveArgData = FALSE; // If TRUE, we're simulating the data.
TexChunk *currentArgument = NULL;
TexChunk *nextChunk = NULL;
Bool isArgOptional = FALSE;
Bool noArgs = 0;
TexChunk *TopLevel = NULL;
wxList MacroDefs(wxKEY_STRING);
wxStringList IgnorableInputFiles; // Ignorable \input files, e.g. psbox.tex
char *BigBuffer = NULL; // For reading in large chunks of text
TexMacroDef *SoloBlockDef = NULL;
void TexOutput(char *s, Bool ordinaryText)
{
int len = strlen(s);
// Update current column, but only if we're guaranteed to
// be ordinary text (not mark-up stuff)
if (ordinaryText)
for (int i = 0; i < len; i++)
{
if (s[i] == 13 || s[i] == 10)
currentColumn = 0;
else
currentColumn ++;
}
if (CurrentOutput1)
fprintf(CurrentOutput1, "%s", s);
if (CurrentOutput2)
fprintf(CurrentOutput2, "%s", s);
}
/*
* Try to find a Latex macro, in one of the following forms:
* (1) \begin{} ... \end{}
* (2) \macroname{arg1}...{argn}
* (3) {\bf arg1}
*/
TexMacroDef *MatchMacro(char *buffer, int *pos, char **env, Bool *parseToBrace)
{
*parseToBrace = TRUE;
int i = (*pos);
TexMacroDef *def = NULL;
// First, try to find begin{thing}
if (strncmp(buffer+i, "begin{", 6) == 0)
{
i += 6;
wxNode *node = MacroDefs.First();
while (node && !def)
{
if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
{ def = (TexMacroDef *)node->Data();
i += strlen(node->key.string); }
else node = node->Next();
}
if (def)
{
*pos = i + 1;
*env = def->name;
return def;
}
else return NULL;
}
// Failed, so try to find macro from definition list
wxNode *node = MacroDefs.First();
while (node && !def)
{
if (strncmp(buffer+i, node->key.string, strlen(node->key.string)) == 0)
{ def = (TexMacroDef *)node->Data();
i += strlen(node->key.string); }
else node = node->Next();
}
if (def)
{
// We want to check whether this is a space-consuming macro
// (e.g. {\bf word})
// No brace, e.g. \input thing.tex instead of \input{thing}
if ((def->no_args > 0) && ((buffer[i] == 32) || (buffer[i] == '=')))
{
i ++;
*parseToBrace = FALSE;
}
*pos = i;
return def;
}
return NULL;
}
Bool FindEndEnvironment(char *buffer, int *pos, char *env)
{
int i = (*pos);
// Try to find end{thing}
if ((strncmp(buffer+i, "end{", 4) == 0) &&
(strncmp(buffer+i+4, env, strlen(env)) == 0))
{
*pos = i + 5 + strlen(env);
return TRUE;
}
else return FALSE;
}
Bool readingVerbatim = FALSE;
Bool readInVerbatim = FALSE; // Within a verbatim, but not nec. verbatiminput
Bool read_a_line(char *buf)
{
if (CurrentInputIndex < 0)
{
buf[0] = 0;
return FALSE;
}
int ch = -2;
int i = 0;
buf[0] = 0;
while (ch != EOF && ch != 10)
{
ch = getc(Inputs[CurrentInputIndex]);
if (ch != EOF)
{
// Check for 2 consecutive newlines and replace with \par
if (ch == 10 && !readInVerbatim)
{
int ch1 = getc(Inputs[CurrentInputIndex]);
if ((ch1 == 10) || (ch1 == 13))
{
// Eliminate newline (10) following DOS linefeed
if (ch1 == 13) ch1 = getc(Inputs[CurrentInputIndex]);
buf[i] = 0;
strcat(buf, "\\par\n");
i += 6;
}
else
{
ungetc(ch1, Inputs[CurrentInputIndex]);
buf[i] = ch;
i ++;
}
}
else
{
buf[i] = ch;
i ++;
}
}
else
{
buf[i] = 0;
fclose(Inputs[CurrentInputIndex]);
Inputs[CurrentInputIndex] = NULL;
if (CurrentInputIndex > 0) ch = ' '; // No real end of file
CurrentInputIndex --;
if (readingVerbatim)
{
readingVerbatim = FALSE;
readInVerbatim = FALSE;
strcat(buf, "\\end{verbatim}\n");
return FALSE;
}
}
}
buf[i] = 0;
// Read a verbatim input file as if it were a verbatim environment
if (strncmp(buf, "\\verbatiminput", 14) == 0)
{
int wordLen = 14;
char *fileName = buf + wordLen + 1;
int j = i - 1;
buf[j] = 0;
// thing}\par -- eliminate the \par!
if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
{
j -= 5;
buf[j] = 0;
}
if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
char *actualFile = TexPathList.FindValidPath(fileName);
if (!actualFile)
{
char errBuf[300];
strcpy(errBuf, "Could not find file: ");
strncat(errBuf, fileName, 100);
OnError(errBuf);
}
else
{
CurrentInputIndex ++;
Inputs[CurrentInputIndex] = fopen(actualFile, "r");
if (!Inputs[CurrentInputIndex])
{
CurrentInputIndex --;
OnError("Could not open verbatiminput file.");
}
else
{
readingVerbatim = TRUE;
readInVerbatim = TRUE;
strcpy(buf, "\\begin{verbatim}\n");
return FALSE;
}
}
return FALSE;
}
else if (strncmp(buf, "\\input", 6) == 0 || strncmp(buf, "\\helpinput", 10) == 0 ||
strncmp(buf, "\\include", 8) == 0)
{
int wordLen;
if (strncmp(buf, "\\input", 6) == 0)
wordLen = 6;
else
if (strncmp(buf, "\\include", 8) == 0)
wordLen = 8;
else
wordLen = 10;
char *fileName = buf + wordLen + 1;
int j = i - 1;
buf[j] = 0;
// \input{thing}\par -- eliminate the \par!
if (strncmp((buf + strlen(buf)-5), "\\par", 4) == 0)
{
j -= 5;
buf[j] = 0;
}
if (buf[j-1] == '}') buf[j-1] = 0; // Ignore final brace
// Ignore some types of input files (e.g. macro definition files)
char *fileOnly = FileNameFromPath(fileName);
if (IgnorableInputFiles.Member(fileOnly))
return read_a_line(buf);
char *actualFile = TexPathList.FindValidPath(fileName);
if (!actualFile)
{
char errBuf[300];
strcpy(errBuf, "Could not find file: ");
strncat(errBuf, fileName, 100);
OnError(errBuf);
}
else
{
CurrentInputIndex ++;
Inputs[CurrentInputIndex] = fopen(actualFile, "r");
if (!Inputs[CurrentInputIndex])
{
CurrentInputIndex --;
OnError("Could not open include file.");
}
}
Bool succ = read_a_line(buf);
return succ;
}
if (strncmp(buf, "\\begin{verbatim}", 16) == 0)
readInVerbatim = TRUE;
else if (strncmp(buf, "\\end{verbatim}", 14) == 0)
readInVerbatim = FALSE;
return (ch == EOF);
}
/*
* Parse newcommand
*
*/
Bool ParseNewCommand(char *buffer, int *pos)
{
if (strncmp((buffer+(*pos)), "newcommand", 10) == 0)
{
*pos = *pos + 12;
char commandName[100];
char commandValue[1000];
int noArgs = 0;
int i = 0;
while (buffer[*pos] != '}' && (buffer[*pos] != 0))
{
commandName[i] = buffer[*pos];
*pos += 1;
i ++;
}
commandName[i] = 0;
i = 0;
*pos += 1;
if (buffer[*pos] == '[')
{
*pos += 1;
noArgs = (int)(buffer[*pos]) - 48;
*pos += 1;
}
Bool end = FALSE;
Bool braceCount = 0;
while (!end)
{
char ch = buffer[*pos];
if (ch == '{')
braceCount ++;
else if (ch == '}')
{
braceCount --;
if (braceCount == 0)
end = TRUE;
}
else if (ch == 0)
{
if (!read_a_line(buffer))
end = TRUE;
*pos = 0;
break;
}
commandValue[i] = ch;
i ++;
*pos += 1;
}
commandValue[i] = 0;
CustomMacro *macro = new CustomMacro(commandName, noArgs, NULL);
if (strlen(commandValue) > 0)
macro->macroBody = copystring(commandValue);
if (!CustomMacroList.Find(commandName))
{
CustomMacroList.Append(commandName, macro);
AddMacroDef(commandName, noArgs);
}
return TRUE;
}
else return FALSE;
}
void MacroError(char *buffer)
{
char errBuf[300];
char macroBuf[200];
strcpy(errBuf, "Could not find macro: ");
macroBuf[0] = '\\';
int i = 1;
char ch;
while (((ch = buffer[i-1]) != '\n') && (ch != 0))
{
macroBuf[i] = ch;
i ++;
}
macroBuf[i] = 0;
if (i > 20)
macroBuf[20] = 0;
strcat(errBuf, macroBuf);
OnError(errBuf);
}
/*
* Parse an argument.
* 'environment' specifies the name of the macro IFF if we're looking for the end
* of an environment, e.g. \end{itemize}. Otherwise it's NULL.
* 'parseToBrace' is TRUE if the argument should extend to the next right brace,
* e.g. in {\bf an argument} as opposed to \vskip 30pt
*
*/
int ParseArg(TexChunk *thisArg, wxList& children, char *buffer, int pos, char *environment, Bool parseToBrace, TexChunk *customMacroArgs)
{
Bool eof = FALSE;
BigBuffer[0] = 0;
int buf_ptr = 0;
int len;
Bool isOptional = FALSE;
// Consume leading brace or square bracket, but ONLY if not following
// a space, because this could be e.g. {\large {\bf thing}} where {\bf thing}
// is the argument of \large AS WELL as being a block in its
// own right.
if (!environment)
{
if ((pos > 0) && (buffer[pos-1] != ' ') && buffer[pos] == '{')
pos ++;
else if ((pos > 0) && (buffer[pos-1] != ' ') && (buffer[pos] == '[' || buffer[pos] == '('))
{
isOptional = TRUE;
pos ++;
}
else if ((pos > 1) && (buffer[pos-1] != ' ') && (buffer[pos+1] == '[' || buffer[pos+1] == '('))
{
isOptional = TRUE;
pos += 2;
}
}
// If not parsing to brace, just read the next word
// (e.g. \vskip 20pt)
if (!parseToBrace)
{
int ch = buffer[pos];
while (!eof && ch != 13 && ch != 32 && ch != 10 &&
ch != 0 && ch != '(' && ch != '{')
{
BigBuffer[buf_ptr] = ch;
buf_ptr ++;
pos ++;
ch = buffer[pos];
}
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
return pos;
}
while (!eof)
{
len = strlen(buffer);
if (pos >= len)
{
eof = read_a_line(buffer);
pos = 0;
len = strlen(buffer);
// Check for verbatim
if (strncmp(buffer, "\\begin{verbatim}", 16) == 0)
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
BigBuffer[0] = 0;
buf_ptr = 0;
eof = read_a_line(buffer);
while (!eof && (strncmp(buffer, "\\end{verbatim}", 14) != 0))
{
strcat(BigBuffer, buffer);
buf_ptr += strlen(buffer);
eof = read_a_line(buffer);
}
eof = read_a_line(buffer);
buf_ptr = 0;
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 1;
chunk->name = copystring("verbatim");
TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
arg->argn = 1;
arg->name = copystring("verbatim");
TexChunk *str = new TexChunk(CHUNK_TYPE_STRING);
str->value = copystring(BigBuffer);
children.Append(chunk);
chunk->children.Append(arg);
arg->children.Append(str);
}
}
char ch = buffer[pos];
// End of optional argument -- pretend it's right brace for simplicity
if (isOptional && (ch == ']' || ch == ')'))
ch = '}';
switch (ch)
{
case 0:
case '}': // End of argument
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
thisArg->optional = isOptional;
children.Append(chunk);
}
if (ch == '}') pos ++;
return pos;
break;
}
case '\\':
{
if (buf_ptr > 0) // Finish off the string we've read so far
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
// Try matching \end{environment}
if (environment && FindEndEnvironment(buffer, &pos, environment))
{
// Eliminate newline after an \end{} if possible
if (buffer[pos] == 13)
{
pos ++;
if (buffer[pos] == 10)
pos ++;
}
return pos;
}
if (ParseNewCommand(buffer, &pos))
break;
char *env = NULL;
Bool tmpParseToBrace = TRUE;
TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
if (def)
{
CustomMacro *customMacro = FindCustomMacro(def->name);
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = def->no_args;
chunk->name = copystring(def->name);
if (!customMacro)
children.Append(chunk);
// Eliminate newline after a \begin{} or a \\ if possible
if (env || strcmp(def->name, "\\") == 0)
if (buffer[pos] == 13)
{
pos ++;
if (buffer[pos] == 10)
pos ++;
}
pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
buffer, pos, env, tmpParseToBrace, customMacroArgs);
// If custom macro, parse the body substituting the above found args.
if (customMacro)
{
if (customMacro->macroBody)
{
char macroBuf[300];
// strcpy(macroBuf, "{");
strcpy(macroBuf, customMacro->macroBody);
strcat(macroBuf, "}");
ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
}
// delete chunk; // Might delete children
}
}
else
{
MacroError(buffer+pos);
}
break;
}
// Parse constructs like {\bf thing} as if they were
// \bf{thing}
case '{':
{
pos ++;
if (buffer[pos] == '\\')
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
char *env;
Bool tmpParseToBrace;
TexMacroDef *def = MatchMacro(buffer, &pos, &env, &tmpParseToBrace);
if (def)
{
CustomMacro *customMacro = FindCustomMacro(def->name);
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = def->no_args;
chunk->name = copystring(def->name);
if (!customMacro)
children.Append(chunk);
pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
buffer, pos, NULL, TRUE, customMacroArgs);
// If custom macro, parse the body substituting the above found args.
if (customMacro)
{
if (customMacro->macroBody)
{
char macroBuf[300];
// strcpy(macroBuf, "{");
strcpy(macroBuf, customMacro->macroBody);
strcat(macroBuf, "}");
ParseArg(thisArg, children, macroBuf, 0, NULL, TRUE, chunk);
}
// delete chunk; // Might delete children
}
}
else
{
MacroError(buffer+pos);
}
}
else
{
/*
* If all else fails, we assume that we have
* a pair of braces on their own, so return a `dummy' macro
* definition with just one argument to parse.
*/
if (!SoloBlockDef)
{
SoloBlockDef = new TexMacroDef("solo block", 1, FALSE);
}
// Save text so far
if (buf_ptr > 0)
{
TexChunk *chunk1 = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk1->value = copystring(BigBuffer);
children.Append(chunk1);
}
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = SoloBlockDef->no_args;
chunk->name = copystring(SoloBlockDef->name);
children.Append(chunk);
pos = ParseMacroBody(chunk->name, chunk, chunk->no_args,
buffer, pos, NULL, TRUE, customMacroArgs);
}
break;
}
case '$':
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
if (buffer[pos] == '$')
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 0;
chunk->name = copystring("$$");
children.Append(chunk);
pos ++;
}
else
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 0;
chunk->name = copystring("_$");
children.Append(chunk);
}
break;
}
case '~':
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 0;
chunk->name = copystring("_~");
children.Append(chunk);
break;
}
case '#': // Either treat as a special TeX character or as a macro arg
{
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
if (!customMacroArgs)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 0;
chunk->name = copystring("_#");
children.Append(chunk);
}
else
{
if (isdigit(buffer[pos]))
{
int n = buffer[pos] - 48;
pos ++;
wxNode *node = customMacroArgs->children.Nth(n-1);
if (node)
{
TexChunk *argChunk = (TexChunk *)node->Data();
children.Append(new TexChunk(*argChunk));
}
}
}
break;
}
case '&':
{
// Remove white space before and after the ampersand,
// since this is probably a table column separator with
// some convenient -- but useless -- white space in the text.
while ((buf_ptr > 0) && ((BigBuffer[buf_ptr-1] == ' ') || (BigBuffer[buf_ptr-1] == 9)))
buf_ptr --;
if (buf_ptr > 0)
{
TexChunk *chunk = new TexChunk(CHUNK_TYPE_STRING);
BigBuffer[buf_ptr] = 0;
buf_ptr = 0;
chunk->value = copystring(BigBuffer);
children.Append(chunk);
}
pos ++;
while (buffer[pos] == ' ' || buffer[pos] == 9)
pos ++;
TexChunk *chunk = new TexChunk(CHUNK_TYPE_MACRO);
chunk->no_args = 0;
chunk->name = copystring("_&");
children.Append(chunk);
break;
}
// Eliminate end-of-line comment
case '%':
{
ch = buffer[pos];
while (ch != 10 && ch != 13 && ch != 0)
{
pos ++;
ch = buffer[pos];
}
if (buffer[pos] == 10 || buffer[pos] == 13)
{
pos ++;
if (buffer[pos] == 10) pos ++; // Eliminate newline following DOS line feed
}
break;
}
// Eliminate tab
case 9:
{
BigBuffer[buf_ptr] = ' ';
BigBuffer[buf_ptr+1] = 0;
buf_ptr ++;
pos ++;
break;
}
default:
{
BigBuffer[buf_ptr] = ch;
BigBuffer[buf_ptr+1] = 0;
buf_ptr ++;
pos ++;
break;
}
}
}
return pos;
}
/*
* Consume as many arguments as the macro definition specifies
*
*/
int ParseMacroBody(char *macro_name, TexChunk *parent,
int no_args, char *buffer, int pos,
char *environment, Bool parseToBrace,
TexChunk *customMacroArgs)
{
// Check for a first optional argument
if (buffer[pos] == '[')
no_args ++;
int maxArgs = 0;
for (int i = 0; i < no_args; i++)
{
maxArgs ++;
TexChunk *arg = new TexChunk(CHUNK_TYPE_ARG);
parent->children.Append(arg);
arg->name = copystring(macro_name);
arg->argn = maxArgs;
// To parse the first arg of a 2 arg \begin{thing}{arg} ... \end{thing}
// have to fool parser into thinking this is a regular kind of block.
char *actualEnv;
if ((no_args == 2) && (i == 0))
actualEnv = NULL;
else
actualEnv = environment;
pos = ParseArg(arg, arg->children, buffer, pos, actualEnv, parseToBrace, customMacroArgs);
// If we've encountered an OPTIONAL argument, go another time around
// the loop, because we've got more than we thought.
// Hopefully optional args don't occur at the end of a macro use
// or we might miss it.
// Don't increment no of times round loop if the first optional arg
// -- we already did it before the loop.
if (arg->optional && (i > 0))
i --;
}
parent->no_args = maxArgs;
// Tell each argument how many args there are (useful when processing an arg)
wxNode *node = parent->children.First();
while (node)
{
TexChunk *chunk = (TexChunk *)node->Data();
chunk->no_args = maxArgs;
node = node->Next();
}
return pos;
}
Bool TexLoadFile(char *filename, char *customMacroFile)
{
strcpy(TexFileRoot, filename);
StripExtension(TexFileRoot);
sprintf(TexBibName, "%s.bb", TexFileRoot);
sprintf(TexTmpBibName, "%s.bb1", TexFileRoot);
TexPathList.EnsureFileAccessible(filename);
#ifdef wx_msw
TexPathList.AddEnvList("TEXINPUT");
#endif
#ifdef wx_x
TexPathList.AddEnvList("TEXINPUTS");
#endif
if (!customMacroFile)
customMacroFile = "tex2rtf.ini";
if (TexPathList.FindValidPath(customMacroFile))
ReadCustomMacros(customMacroFile);
static char line_buffer[500];
Inputs[0] = fopen(filename, "r");
if (Inputs[0])
{
read_a_line(line_buffer);
ParseMacroBody("toplevel", TopLevel, 1, line_buffer, 0, NULL, TRUE);
if (Inputs[0]) fclose(Inputs[0]);
return TRUE;
}
else return FALSE;
}
TexMacroDef::TexMacroDef(char *the_name, int n, Bool ig)
{
name = copystring(the_name);
no_args = n;
ignore = ig;
}
TexMacroDef::~TexMacroDef(void)
{
if (name) delete[] name;
}
TexChunk::TexChunk(int the_type)
{
type = the_type;
no_args = 0;
argn = 0;
name = NULL;
value = NULL;
optional = FALSE;
children.DeleteContents(TRUE);
}
TexChunk::TexChunk(TexChunk& toCopy)
{
type = toCopy.type;
no_args = toCopy.no_args;
argn = toCopy.argn;
if (toCopy.name)
name = copystring(toCopy.name);
else
name = NULL;
if (toCopy.value)
value = copystring(toCopy.value);
else
value = NULL;
optional = toCopy.optional;
wxNode *node = toCopy.children.First();
while (node)
{
TexChunk *child = (TexChunk *)node->Data();
children.Append(new TexChunk(*child));
node = node->Next();
}
children.DeleteContents(TRUE);
}
TexChunk::~TexChunk(void)
{
if (name) delete[] name;
if (value) delete[] value;
}
Bool IsArgOptional(void) // Is this argument an optional argument?
{
return isArgOptional;
}
int GetNoArgs(void) // Number of args for this macro
{
return noArgs;
}
/* Gets the text of a chunk on request (must be for small arguments
* only!)
*
*/
void GetArgData1(TexChunk *chunk)
{
switch (chunk->type)
{
case CHUNK_TYPE_MACRO:
{
wxNode *node = MacroDefs.Find(chunk->name);
if (node)
{
TexMacroDef *def = (TexMacroDef *)node->Data();
if (def->ignore)
return;
}
strcat(currentArgData, "\\");
strcat(currentArgData, chunk->name);
node = chunk->children.First();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->Data();
strcat(currentArgData, "{");
GetArgData1(child_chunk);
strcat(currentArgData, "}");
node = node->Next();
}
break;
}
case CHUNK_TYPE_ARG:
{
wxNode *node = chunk->children.First();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->Data();
GetArgData1(child_chunk);
node = node->Next();
}
break;
}
case CHUNK_TYPE_STRING:
{
if (chunk->value)
strcat(currentArgData, chunk->value);
break;
}
}
}
char *GetArgData(void)
{
if (!haveArgData)
{
currentArgData[0] = 0;
GetArgData1(currentArgument);
}
return currentArgData;
}
TexChunk *GetArgChunk(void)
{
return currentArgument;
}
TexChunk *GetNextChunk(void) // Look ahead to the next chunk
{
return nextChunk;
}
TexChunk *GetTopLevelChunk(void)
{
return TopLevel;
}
int GetCurrentColumn(void)
{
return currentColumn;
}
/*
* Traverses document calling functions to allow the client to
* write out the appropriate stuff
*/
void TraverseFromChunk(TexChunk *chunk, wxNode *thisNode, Bool childrenOnly)
{
switch (chunk->type)
{
case CHUNK_TYPE_MACRO:
{
wxNode *node = MacroDefs.Find(chunk->name);
if (node)
{
TexMacroDef *def = (TexMacroDef *)node->Data();
if (def->ignore)
return;
}
if (!childrenOnly)
OnMacro(chunk->name, chunk->no_args, TRUE);
node = chunk->children.First();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->Data();
TraverseFromChunk(child_chunk, node);
node = node->Next();
}
if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
if (!childrenOnly)
OnMacro(chunk->name, chunk->no_args, FALSE);
break;
}
case CHUNK_TYPE_ARG:
{
currentArgument = chunk;
isArgOptional = chunk->optional;
noArgs = chunk->no_args;
// If OnArgument returns FALSE, don't output.
if (childrenOnly || OnArgument(chunk->name, chunk->argn, TRUE))
{
wxNode *node = chunk->children.First();
while (node)
{
TexChunk *child_chunk = (TexChunk *)node->Data();
TraverseFromChunk(child_chunk, node);
node = node->Next();
}
}
currentArgument = chunk;
if (thisNode && thisNode->Next()) nextChunk = (TexChunk *)thisNode->Next()->Data();
isArgOptional = chunk->optional;
noArgs = chunk->no_args;
if (!childrenOnly)
(void)OnArgument(chunk->name, chunk->argn, FALSE);
break;
}
case CHUNK_TYPE_STRING:
{
if (chunk->value)
TexOutput(chunk->value, TRUE);
break;
}
}
}
void TraverseDocument(void)
{
TraverseFromChunk(TopLevel, NULL);
}
void SetCurrentOutput(FILE *fd)
{
CurrentOutput1 = fd;
CurrentOutput2 = NULL;
}
void SetCurrentOutputs(FILE *fd1, FILE *fd2)
{
CurrentOutput1 = fd1;
CurrentOutput2 = fd2;
}
void AddMacroDef(char *name, int n, Bool ignore)
{
MacroDefs.Append(name, new TexMacroDef(name, n, ignore));
}
void TexInitialize(void)
{
for (int i = 0; i < 15; i++)
Inputs[i] = NULL;
IgnorableInputFiles.Add("psbox.tex");
BigBuffer = new char[20000];
AddMacroDef("toplevel", 1);
TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
TopLevel->name = copystring("toplevel");
TopLevel->no_args = 1;
}
void TexCleanUp(void)
{
for (int i = 0; i < 15; i++)
Inputs[i] = NULL;
chapterNo = 0;
sectionNo = 0;
subsectionNo = 0;
subsubsectionNo = 0;
figureNo = 0;
CurrentOutput1 = NULL;
CurrentOutput2 = NULL;
CurrentInputIndex = 0;
haveArgData = FALSE;
noArgs = 0;
if (TopLevel)
delete TopLevel;
TopLevel = new TexChunk(CHUNK_TYPE_MACRO);
TopLevel->name = copystring("toplevel");
TopLevel->no_args = 1;
DocumentTitle = NULL;
DocumentAuthor = NULL;
DocumentDate = NULL;
CurrentLabel = NULL;
DocumentStyle = LATEX_REPORT;
MinorDocumentStyle = 0;
BibliographyStyleString = copystring("plain");
DocumentStyleString = copystring("report");
SetFontSizes(10);
wxNode *node = CustomMacroList.First();
while (node)
{
CustomMacro *macro = (CustomMacro *)node->Data();
delete macro;
delete node;
node = CustomMacroList.First();
}
node = TexReferences.First();
while (node)
{
TexRef *ref = (TexRef *)node->Data();
delete ref;
delete node;
node = TexReferences.First();
}
node = BibList.First();
while (node)
{
BibEntry *entry = (BibEntry *)node->Data();
delete entry;
delete node;
node = BibList.First();
}
CitationList.Clear();
ResetTopicCounter();
}
// There is likely to be one set of macros used by all utilities.
void DefineDefaultMacros(void)
{
// Put names which subsume other names at the TOP
// so they get recognized first
AddMacroDef("abstract", 1);
AddMacroDef("addcontentsline", 3);
AddMacroDef("addtocounter", 2);
AddMacroDef("alph", 1);
AddMacroDef("Alph", 1);
AddMacroDef("appendix", 0);
AddMacroDef("arabic", 1);
AddMacroDef("array", 1);
AddMacroDef("author", 1);
AddMacroDef("backslash", 0);
AddMacroDef("baselineskip", 1);
AddMacroDef("bf", 1);
AddMacroDef("bibitem", 2); // For convenience, bibitem has 2 args: label and item.
// The Latex syntax permits writing as 2 args.
AddMacroDef("bibliographystyle", 1);
AddMacroDef("bibliography", 1);
AddMacroDef("boxit", 1);
AddMacroDef("caption*", 1);
AddMacroDef("caption", 1);
AddMacroDef("cdots", 0);
AddMacroDef("centerline", 1);
AddMacroDef("centering", 0);
AddMacroDef("center", 1);
AddMacroDef("cextract", 0);
AddMacroDef("chapter*", 1);
AddMacroDef("chapter", 1);
AddMacroDef("cinsert", 0);
AddMacroDef("cite", 1);
AddMacroDef("class", 1);
AddMacroDef("cleardoublepage", 0);
AddMacroDef("clearpage", 0);
AddMacroDef("cline", 1);
AddMacroDef("clipsfunc", 3);
AddMacroDef("columnsep", 1);
AddMacroDef("comment", 1, TRUE);
AddMacroDef("copyright", 0);
AddMacroDef("cparam", 2);
AddMacroDef("date", 1);
AddMacroDef("description", 1);
AddMacroDef("destruct", 1);
AddMacroDef("documentstyle", 1);
AddMacroDef("document", 1);
AddMacroDef("doublespace", 1);
AddMacroDef("em", 1);
AddMacroDef("enumerate", 1);
AddMacroDef("equation", 1);
AddMacroDef("evensidemargin", 1);
AddMacroDef("fbox", 1);
AddMacroDef("figure", 1);
AddMacroDef("flushleft", 1);
AddMacroDef("flushright", 1);
AddMacroDef("footheight", 1);
AddMacroDef("footnote", 1);
AddMacroDef("footskip", 1);
AddMacroDef("framebox", 1);
AddMacroDef("functionsection", 1);
AddMacroDef("func", 3);
AddMacroDef("glossary", 1);
AddMacroDef("gloss", 1);
AddMacroDef("headheight", 1);
AddMacroDef("helpignore", 1, TRUE);
AddMacroDef("helponly", 1);
AddMacroDef("helpinput", 1);
AddMacroDef("helpfontfamily", 1);
AddMacroDef("helpfontsize", 1);
AddMacroDef("helprefn", 2);
AddMacroDef("helpref", 2);
AddMacroDef("hfill", 0);
AddMacroDef("hline", 0);
AddMacroDef("hrule", 0);
AddMacroDef("hspace*", 1);
AddMacroDef("hspace", 1);
AddMacroDef("hskip*", 1);
AddMacroDef("hskip", 1);
AddMacroDef("huge", 1);
AddMacroDef("Huge", 1);
AddMacroDef("HUGE", 1);
AddMacroDef("includeonly", 1);
AddMacroDef("include", 1);
AddMacroDef("index", 1);
AddMacroDef("input", 1);
AddMacroDef("itemize", 1);
AddMacroDef("item", 0);
AddMacroDef("image", 2);
AddMacroDef("it", 1);
AddMacroDef("kill", 0);
AddMacroDef("label", 1);
AddMacroDef("large", 1);
AddMacroDef("Large", 1);
AddMacroDef("LARGE", 1);
AddMacroDef("LaTeX", 0);
AddMacroDef("lbox", 1);
AddMacroDef("ldots", 0);
AddMacroDef("linebreak", 0);
AddMacroDef("listoffigures", 0);
AddMacroDef("listoftables", 0);
AddMacroDef("makeglossary", 0);
AddMacroDef("makeindex", 0);
AddMacroDef("maketitle", 0);
AddMacroDef("markright", 1);
AddMacroDef("markboth", 2);
AddMacroDef("marginparwidth", 1);
AddMacroDef("marginpar", 1);
AddMacroDef("mbox", 1);
AddMacroDef("membersection", 1);
AddMacroDef("member", 2);
AddMacroDef("multicolumn", 3);
AddMacroDef("myheading", 1);
AddMacroDef("newcounter", 1);
AddMacroDef("newline", 0);
AddMacroDef("newpage", 0);
AddMacroDef("nocite", 1);
AddMacroDef("noindent", 0);
AddMacroDef("nolinebreak", 0);
AddMacroDef("nopagebreak", 0);
AddMacroDef("normalsize", 1);
AddMacroDef("onecolumn", 0);
AddMacroDef("oddsidemargin", 1);
AddMacroDef("pagebreak", 0);
AddMacroDef("pageref", 1);
AddMacroDef("pagestyle", 1);
AddMacroDef("pagenumbering", 1);
AddMacroDef("paragraph*", 1);
AddMacroDef("paragraph", 1);
AddMacroDef("param", 2);
AddMacroDef("parindent", 1);
AddMacroDef("parskip", 1);
AddMacroDef("part*", 1);
AddMacroDef("part", 1);
AddMacroDef("par", 0);
AddMacroDef("pfunc", 3);
AddMacroDef("picture", 1);
AddMacroDef("printindex", 0);
AddMacroDef("psboxto", 1);
AddMacroDef("psbox", 1);
AddMacroDef("quote", 1);
AddMacroDef("quotation", 1);
AddMacroDef("raggedbottom", 0);
AddMacroDef("raggedleft", 0);
AddMacroDef("raggedright", 0);
AddMacroDef("ref", 1);
AddMacroDef("rm", 1);
AddMacroDef("roman", 1);
AddMacroDef("Roman", 1);
// AddMacroDef("row", 1);
AddMacroDef("rtfsp", 0);
// AddMacroDef("ruledrow", 1);
AddMacroDef("sc", 1);
AddMacroDef("section*", 1);
AddMacroDef("section", 1);
AddMacroDef("setcounter", 2);
AddMacroDef("sf", 1);
AddMacroDef("shortcite", 1);
AddMacroDef("singlespace", 1);
AddMacroDef("sloppypar", 1);
AddMacroDef("sloppy", 0);
AddMacroDef("sl", 1);
AddMacroDef("small", 1);
AddMacroDef("subitem", 0);
AddMacroDef("subparagraph*", 1);
AddMacroDef("subparagraph", 1);
AddMacroDef("special", 1);
AddMacroDef("subsection*", 1);
AddMacroDef("subsection", 1);
AddMacroDef("subsubsection*", 1);
AddMacroDef("subsubsection", 1);
AddMacroDef("tabbing", 2);
AddMacroDef("tableofcontents", 0);
AddMacroDef("table", 1);
AddMacroDef("tabular", 2);
AddMacroDef("tab", 0);
AddMacroDef("TeX", 0);
AddMacroDef("textwidth", 1);
AddMacroDef("textheight", 1);
AddMacroDef("thebibliography", 2);
AddMacroDef("titlepage", 1);
AddMacroDef("title", 1);
AddMacroDef("tiny", 1);
AddMacroDef("today", 0);
AddMacroDef("topmargin", 1);
AddMacroDef("topskip", 1);
AddMacroDef("tt", 1);
AddMacroDef("typein", 1);
AddMacroDef("typeout", 1);
AddMacroDef("twocolumn", 0);
AddMacroDef("underline", 1);
AddMacroDef("vdots", 0);
AddMacroDef("verbatiminput", 1);
AddMacroDef("verbatim", 1);
AddMacroDef("verb", 0);
AddMacroDef("verse", 1);
AddMacroDef("vfill", 0);
AddMacroDef("vline", 0);
AddMacroDef("void", 0);
AddMacroDef("vrule", 0);
AddMacroDef("vspace*", 1);
AddMacroDef("vskip*", 1);
AddMacroDef("vspace", 1);
AddMacroDef("vskip", 1);
AddMacroDef("wxclips", 0);
AddMacroDef(" ", 0);
AddMacroDef("\\", 0);
AddMacroDef("|", 0);
AddMacroDef("/", 0);
AddMacroDef("_", 0);
AddMacroDef("&", 0);
AddMacroDef("%", 0);
AddMacroDef("$", 0);
AddMacroDef("#", 0);
AddMacroDef("(", 0);
AddMacroDef(")", 0);
AddMacroDef("{", 0);
AddMacroDef("}", 0);
AddMacroDef("=", 0);
AddMacroDef(">", 0);
AddMacroDef("<", 0);
AddMacroDef("+", 0);
AddMacroDef("-", 0);
AddMacroDef("'", 0);
AddMacroDef("`", 0);
}
/*
* Default behaviour, should be called by client if can't match locally.
*
*/
// Called on start/end of macro examination
void DefaultOnMacro(char *name, int no_args, Bool start)
{
// Default behaviour for abstract: should really do better than this.
if (strcmp(name, "abstract") == 0)
{
if (start)
{
OnMacro("flushleft", 1, TRUE);
OnArgument("flushleft", 1, TRUE);
OnMacro("bf", 1, TRUE);
OnArgument("bf", 1, TRUE);
OnMacro("LARGE", 1, TRUE);
OnArgument("LARGE", 1, TRUE);
TexOutput("Abstract", TRUE);
OnArgument("LARGE", 1, FALSE);
OnMacro("LARGE", 1, FALSE);
OnArgument("bf", 1, FALSE);
OnMacro("bf", 1, FALSE);
OnArgument("flushleft", 1, FALSE);
OnMacro("par", 0, TRUE);
OnMacro("par", 0, TRUE);
OnMacro("par", 0, TRUE);
OnMacro("par", 0, FALSE);
OnMacro("par", 0, FALSE);
OnMacro("par", 0, FALSE);
}
}
else if ((strcmp(name, "cinsert") == 0) && start)
TexOutput("<<", TRUE);
else if ((strcmp(name, "cextract") == 0) && start)
TexOutput(">>", TRUE);
else if ((strcmp(name, "destruct") == 0) && start)
TexOutput("~", TRUE);
else if ((strcmp(name, "~") == 0) && start)
TexOutput("~", TRUE);
else if ((strcmp(name, "_~") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, ",") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, ":") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, ";") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, "!") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, "_") == 0) && start)
TexOutput("_", TRUE);
else if ((strcmp(name, "#") == 0) && start)
TexOutput("#", TRUE);
else if ((strcmp(name, "&") == 0) && start)
TexOutput("&", TRUE);
else if ((strcmp(name, " ") == 0) && start)
TexOutput(" ", TRUE);
else if ((strcmp(name, "|") == 0) && start)
TexOutput("|", TRUE);
else if ((strcmp(name, "%") == 0) && start)
TexOutput("%", TRUE);
else if ((strcmp(name, "$") == 0) && start)
TexOutput("$", TRUE);
else if ((strcmp(name, "(") == 0) && start)
TexOutput("", TRUE);
else if ((strcmp(name, ")") == 0) && start)
TexOutput("", TRUE);
else if ((strcmp(name, "{") == 0) && start)
TexOutput("{", TRUE);
else if ((strcmp(name, "}") == 0) && start)
TexOutput("}", TRUE);
else if ((strcmp(name, "copyright") == 0) && start)
TexOutput("(c)", TRUE);
else if ((strcmp(name, "backslash") == 0) && start)
TexOutput("\\", TRUE);
else if (start && (strcmp(name, "ldots") == 0 || strcmp(name, "cdots") == 0))
TexOutput("...", TRUE);
else if (start && (strcmp(name, "vdots") == 0))
TexOutput("|", TRUE);
else if ((strcmp(name, "LaTeX") == 0) && start)
TexOutput("LaTeX", TRUE);
else if ((strcmp(name, "TeX") == 0) && start)
TexOutput("TeX", TRUE);
else if ((strcmp(name, "pounds") == 0) && start)
TexOutput("ú", TRUE);
else if (strcmp(name, "sl") == 0)
{
OnMacro("it", no_args, start);
}
else if (strcmp(name, "today") == 0)
{
#ifdef wx_x
long when;
#endif
#ifdef wx_msw
time_t when;
#endif
(void) time(&when);
TexOutput(ctime(&when), TRUE);
}
else if (strcmp(name, "noindent") == 0)
{
if (start)
ParIndent = 0;
}
// Default way of writing the references title
else if (strcmp(name, "references") == 0 && start)
{
OnMacro("flushleft", 1, TRUE);
OnArgument("flushleft", 1, TRUE);
OnMacro("LARGE", 1, TRUE);
OnArgument("LARGE", 1, TRUE);
OnMacro("bf", 1, TRUE);
OnArgument("bf", 1, TRUE);
TexOutput("References");
OnArgument("bf", 1, FALSE);
OnMacro("bf", 1, FALSE);
OnArgument("LARGE", 1, FALSE);
OnMacro("LARGE", 1, FALSE);
OnArgument("flushleft", 1, FALSE);
OnMacro("flushleft", 1, FALSE);
OnMacro("par", 0, TRUE);
OnMacro("par", 0, FALSE);
}
}
// Called on start/end of argument examination
Bool DefaultOnArgument(char *macro_name, int arg_no, Bool start)
{
if (strcmp(macro_name, "ref") == 0)
{
if (arg_no == 1 && start)
{
char *refName = GetArgData();
if (refName)
{
wxNode *node = TexReferences.Find(refName);
if (node)
{
TexRef *texRef = (TexRef *)node->Data();
// Must strip the 'section' or 'chapter' or 'figure' text
// from a normal 'ref' reference
char buf[150];
strcpy(buf, texRef->sectionNumber);
int len = strlen(buf);
int i = 0;
if (strcmp(buf, "??") != 0)
{
while (i < len)
{
if (buf[i] == ' ')
{
i ++;
break;
}
else i ++;
}
}
TexOutput(texRef->sectionNumber + i, TRUE);
}
else
{
char buf[300];
TexOutput("??", TRUE);
sprintf(buf, "Warning: unresolved reference %s.", refName);
OnInform(buf);
}
}
else TexOutput("??", TRUE);
return FALSE;
}
}
else if (strcmp(macro_name, "label") == 0)
{
if (start && (arg_no == 1))
{
if (CurrentLabel) delete CurrentLabel;
CurrentLabel = copystring(GetArgData());
}
return FALSE;
}
else if (strcmp(macro_name, "author") == 0)
{
if (start && (arg_no == 1))
DocumentAuthor = GetArgChunk();
return FALSE;
}
else if (strcmp(macro_name, "date") == 0)
{
if (start && (arg_no == 1))
DocumentDate = GetArgChunk();
return FALSE;
}
else if (strcmp(macro_name, "title") == 0)
{
if (start && (arg_no == 1))
DocumentTitle = GetArgChunk();
return FALSE;
}
else if (strcmp(macro_name, "documentstyle") == 0)
{
if (start && !IsArgOptional())
{
DocumentStyleString = copystring(GetArgData());
if (strncmp(DocumentStyleString, "art", 3) == 0)
DocumentStyle = LATEX_ARTICLE;
else if (strncmp(DocumentStyleString, "rep", 3) == 0)
DocumentStyle = LATEX_REPORT;
else if (strncmp(DocumentStyleString, "book", 4) == 0 ||
strncmp(DocumentStyleString, "thesis", 6) == 0)
DocumentStyle = LATEX_BOOK;
else if (strncmp(DocumentStyleString, "letter", 6) == 0)
DocumentStyle = LATEX_LETTER;
else if (strncmp(DocumentStyleString, "slides", 6) == 0)
DocumentStyle = LATEX_SLIDES;
if (StringMatch("10", DocumentStyleString))
SetFontSizes(10);
else if (StringMatch("11", DocumentStyleString))
SetFontSizes(11);
else if (StringMatch("12", DocumentStyleString))
SetFontSizes(12);
OnMacro("helpfontsize", 1, TRUE);
sprintf(currentArgData, "%d", normalFont);
haveArgData = TRUE;
OnArgument("helpfontsize", 1, TRUE);
OnArgument("helpfontsize", 1, FALSE);
haveArgData = FALSE;
OnMacro("helpfontsize", 1, FALSE);
}
else if (start && IsArgOptional())
{
char *optionalStyle = copystring(GetArgData());
if (StringMatch("10", optionalStyle))
SetFontSizes(10);
else if (StringMatch("11", optionalStyle))
SetFontSizes(11);
else if (StringMatch("12", optionalStyle))
SetFontSizes(12);
}
return FALSE;
}
else if (strcmp(macro_name, "bibliographystyle") == 0)
{
if (start && !IsArgOptional())
BibliographyStyleString = copystring(GetArgData());
return FALSE;
}
else if (strcmp(macro_name, "cite") == 0 || strcmp(macro_name, "shortcite") == 0)
{
if (start && !IsArgOptional())
{
char *citeKey = GetArgData();
AddCitation(citeKey);
wxNode *node = TexReferences.Find(citeKey);
if (node)
{
TexRef *ref = (TexRef *)node->Data();
TexOutput(ref->sectionNumber, TRUE);
if (strcmp(ref->sectionNumber, "??") == 0)
{
char buf[300];
sprintf(buf, "Warning: unresolved citation %s.", citeKey);
OnInform(buf);
}
}
return FALSE;
}
}
else if (strcmp(macro_name, "nocite") == 0)
{
if (start && !IsArgOptional())
{
char *citeKey = GetArgData();
AddCitation(citeKey);
return FALSE;
}
}
else if (strcmp(macro_name, "helpfontsize") == 0)
{
if (start)
{
char *data = GetArgData();
if (strcmp(data, "10") == 0)
SetFontSizes(10);
else if (strcmp(data, "11") == 0)
SetFontSizes(11);
else if (strcmp(data, "12") == 0)
SetFontSizes(12);
return FALSE;
}
}
else if (strcmp(macro_name, "pageref") == 0)
{
if (start)
{
TexOutput(" ??", TRUE);
return FALSE;
}
}
else if (strcmp(macro_name, "parskip") == 0)
{
if (start && arg_no == 1)
{
char *data = GetArgData();
ParSkip = ParseUnitArgument(data);
return FALSE;
}
}
else if (strcmp(macro_name, "parindent") == 0)
{
if (start && arg_no == 1)
{
char *data = GetArgData();
ParIndent = ParseUnitArgument(data);
return FALSE;
}
}
else if (strcmp(macro_name, "sl") == 0)
{
return OnArgument("it", arg_no, start);
}
else if (strcmp(macro_name, "typeout") == 0)
{
if (start)
OnInform(GetArgData());
}
else if (strcmp(macro_name, "footnote") == 0)
{
if (start)
TexOutput(" (", TRUE);
else
TexOutput(")", TRUE);
}
else if (strcmp(macro_name, "bibliography") == 0)
{
if (start)
{
FILE *fd;
char ch;
char smallBuf[2];
smallBuf[1] = 0;
if (fd = fopen(TexBibName, "r"))
{
ch = getc(fd);
smallBuf[0] = ch;
while (ch != EOF)
{
TexOutput(smallBuf);
ch = getc(fd);
smallBuf[0] = ch;
}
fclose(fd);
}
else
{
OnInform("Run Tex2RTF again to include bibliography.");
}
// Read in the .bib file, resolve all known references, write out the RTF.
char *bibFile = GetArgData();
char fileBuf[300];
strcpy(fileBuf, bibFile);
char *actualFile = TexPathList.FindValidPath(fileBuf);
if (!actualFile)
{
strcat(fileBuf, ".bib");
actualFile = TexPathList.FindValidPath(fileBuf);
}
Bool success = FALSE;
if (actualFile)
{
if (ReadBib(actualFile))
{
ResolveBibReferences();
success = TRUE;
}
}
if (success)
{
// Write it a new bib section in the appropriate format.
FILE *save1 = CurrentOutput1;
FILE *save2 = CurrentOutput2;
FILE *Biblio = fopen(TexTmpBibName, "w");
SetCurrentOutput(Biblio);
OutputBib();
fclose(Biblio);
if (FileExists(TexTmpBibName))
{
if (FileExists(TexBibName)) wxRemoveFile(TexBibName);
wxRenameFile(TexTmpBibName, TexBibName);
}
SetCurrentOutputs(save1, save2);
}
else
OnError(".bib file not found or malformed.");
return FALSE;
}
}
else if (strcmp(macro_name, "multicolumn") == 0)
{
if (start && (arg_no == 3))
return TRUE;
else
return FALSE;
}
else if (strcmp(macro_name, "pagestyle") == 0 ||
strcmp(macro_name, "cline") == 0 ||
strcmp(macro_name, "arabic") == 0 ||
strcmp(macro_name, "alph") == 0 ||
strcmp(macro_name, "Alph") == 0 ||
strcmp(macro_name, "roman") == 0 ||
strcmp(macro_name, "Roman") == 0 ||
strcmp(macro_name, "setcounter") == 0 ||
strcmp(macro_name, "addtocounter") == 0 ||
strcmp(macro_name, "addcontentsline") == 0 ||
strcmp(macro_name, "newcounter") == 0 ||
strcmp(macro_name, "textwidth") == 0 ||
strcmp(macro_name, "textheight") == 0 ||
strcmp(macro_name, "baselineskip") == 0 ||
strcmp(macro_name, "vspace*") == 0 ||
strcmp(macro_name, "hspace*") == 0 ||
strcmp(macro_name, "vspace") == 0 ||
strcmp(macro_name, "hspace") == 0 ||
strcmp(macro_name, "vskip*") == 0 ||
strcmp(macro_name, "hskip*") == 0 ||
strcmp(macro_name, "vskip") == 0 ||
strcmp(macro_name, "hskip") == 0 ||
strcmp(macro_name, "pagenumbering") == 0)
return FALSE;
return TRUE;
}